import base

class StageHandler(base.AbstractStage):
    """ Manage Stage as consecutive situations """
    def __init__(self, stages):
        super(StageHandler, self).__init__()
        self.stages = stages
        self.actual = -1

    def begin(self, button, *args, **kwargs):
        #Override begin suscription to accept button
        assert self.actual == -1
        super(StageHandler, self).begin(*args, **kwargs)
        self.button = button
        self.next()


    def next(self):
        self.actual += 1
        if self.actual != 0:
            #Isn't first element
            self.stage_suscription.unsuscribe()
        if self.actual < len(self.stages):
            #There are stage left
            self.stage_suscription = self.stages[self.actual].suscribe('finnish' , lambda x: self.next())
            self.stages[self.actual].begin(self.button)
        else:
            #End of stages
            self.actual = -1
            self.dispatch('finnish', self)


class SingleStage(base.StimuliStage):
    """
    Situation where the subject is tested against a single stimulus. One at a 
    time.
    """
    def begin(self, *args, **kwargs):
        super(SingleStage, self).begin(*args, **kwargs)

    def finnish(self, *args, **kwargs):
        super(SingleStage, self).finnish(*args, **kwargs)


class MultiStage(base.StimuliStage):
    """Situation where the subject is tested against two stimuli."""

    def begin(self, *args, **kwargs):
        super(MultiStage, self).begin(*args, **kwargs)

    def finnish(self, *args, **kwargs):
        super(MultiStage, self).finnish(*args, **kwargs)

class DecisionStage(base.StimuliStage):
    """ 
    User must choose among previous shown stimuli. 
    """
    def begin(self, *args, **kwargs):
        self.stimuli.begin_choose()
        super(DecisionStage, self).begin(*args, **kwargs)

    def finnish(self, *args, **kwargs):
        super(DecisionStage, self).finnish(*args, **kwargs)
        self.stimuli.finnnish_choose()

class EmptyStage(base.ButtonStage):
    """ Cleans the screen. """
    def __init__(self, models, *args, **kwargs):
        super(EmptyStage, self).__init__(*args, **kwargs)
        self.models = models

    def begin(self, *args, **kwargs):
        for model in self.models:
            model.hide()
        super(EmptyStage, self).begin(*args, **kwargs)

    def finnish(self, *args, **kwargs):
        super(EmptyStage, self).finnish(*args, **kwargs)

class AppearanceStage(base.ButtonStage):
    """ Subject and Tester appears in game. """
    def __init__(self, subject, tester, sprite_repo, *args, **kwargs):
        super(AppearanceStage, self).__init__(*args, **kwargs)
        self.tester = tester
        self.subject = subject
        self.sprite_repo = sprite_repo

    def begin(self, button):
        super(AppearanceStage, self).begin(button)
        [sprite.hide() for sprite in self.sprite_repo.values()]
        self.subject.show_sprite()
        self.tester.show_sprite()
        self.finnish()

class PresentationStage(base.ButtonStage):
    """ User is presentated a part of the game. """
    def __init__(self, model, * args, **kwargs):
        super(PresentationStage, self).__init__(*args, **kwargs)
        self.model = model

    def begin(self, *args, **kwargs):
        super(PresentationStage, self).begin(*args, **kwargs)
        self.model.show_sprite()

